//*****************************************************************
// PIDControlThread.cpp
//
//  Created on: Jan 21, 2012
//      Author: Christopher Wood
//              Robert Livosi
//
//  $Id: PIDControlThread.cpp 23 2012-01-28 02:51:05Z caw4567@gmail.com $
//*****************************************************************

#include "PIDControlThread.h"
#include "PIDTransformThread.h"

/**
 * The (friendly) user input thread function.
 *
 * @param arg - pointer to the host PIDControlThread object.
 */
void* userInputThread(void* arg);

/**
 * Default constructor that sets the transform and I/O threads.
 *
 * @param tThread - the desired transform thread to control.
 * @param ioGroup - the I/O group that is managed.
 */
PIDControlThread::PIDControlThread(TransformThread* tThread, IOThreadGroup* ioGroup)
	: ControlThread(tThread, ioGroup)
{
}

/**
 * Default destructor.
 */
PIDControlThread::~PIDControlThread()
{
}

/**
 * The (friendly) user input thread function.
 *
 * @param arg - pointer to the host PIDControlThread object.
 */
void* userInputThread(void* arg)
{
	ControlThread* controller = (PIDControlThread*)arg;
	PIDTransformThread* transformer = dynamic_cast<PIDTransformThread*>(controller->getTransformer());
	float setPoint = 0.0;
	float kp = 0.0;
	float ki = 0.0;
	float kd = 0.0;
	int continueFlag = 1;

	// Loop and collect user input to modify the PID controller on the fly.
	while (continueFlag)
	{
		// Set point for the system
		cout << "Enter set point: ";
		cin >> setPoint;
		transformer->setReference(setPoint);

		// Proportional parameter
		cout << "Enter Kp: ";
		cin >> kp;
		transformer->setKp(kp);

		// Integrator parameter
		cout << "Enter Ki: ";
		cin >> ki;
		transformer->setKi(ki);

		// Differential parameter
		cout << "Enter Kd: ";
		cin >> kd;
		transformer->setKd(kd);

		// Termination flag
		cout << "0 to terminate, 1 to continue: ";
		cin >> continueFlag;
	}

	// Terminate all threads for cleanup and then exit
	transformer->setThreadState(false);
	transformer->release();
	(controller->getIOThreadGroup())->setInputThreadState(false);
	(controller->getIOThreadGroup())->releaseInputThread();
	(controller->getIOThreadGroup())->setOutputThreadState(false);
	(controller->getIOThreadGroup())->releaseOutputThread();

	// We're complete now.
	controller->setComplete(true);
	pthread_exit(NULL);
}

/**
 * Start the thread.
 */
void PIDControlThread::run()
{
	pthread_create(&threadID, NULL, userInputThread, this);
}
